package com.sc.security.service.impl;

import com.fasterxml.jackson.databind.annotation.JsonAppend;
import com.google.common.base.Preconditions;
import com.sc.security.beans.LogService;
import com.sc.security.common.JsonData;
import com.sc.security.common.RequestHolder;
import com.sc.security.dao.SysDeptMapper;
import com.sc.security.dao.SysUserMapper;
import com.sc.security.exception.ParamException;
import com.sc.security.model.SysDept;
import com.sc.security.service.DeptService;
import com.sc.security.service.LogType;
import com.sc.security.utils.BeanValidator;
import com.sc.security.utils.IpUtil;
import com.sc.security.utils.LevelUtil;
import com.sc.security.vo.DeptVo;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;


@Service
public class DeptServiceImpl implements DeptService {

    @Autowired
    private SysDeptMapper deptMapper;
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private LogService logService;

    public void save(DeptVo deptVo){
        BeanValidator.check(deptVo);
        if (checkExist(deptVo.getParentId(),deptVo.getName(),deptVo.getId())){
            throw new ParamException("同一层级下存在名称相同的部门");
        }
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(deptVo,sysDept);
        sysDept.setLevel(LevelUtil.calculateLevel(getLevel(deptVo.getParentId()),deptVo.getParentId()));
        sysDept.setOperator(RequestHolder.getCurrentUser().getUsername());
        sysDept.setOperateIp(IpUtil.getUserIP(RequestHolder.getCurrentRequest()));
        sysDept.setOperateTime(new Date());
        sysDept.setId(null);
        deptMapper.insertSelective(sysDept);
        logService.saveDeptLog(null,sysDept);
    }

    @Override
    public void update(DeptVo deptVo) {
        BeanValidator.check(deptVo);
        if (checkExist(deptVo.getParentId(),deptVo.getName(),deptVo.getId())){
            throw new ParamException("同一层级下存在名称相同的部门");
        }
        SysDept before = deptMapper.selectByPrimaryKey(deptVo.getId());
        Preconditions.checkNotNull(before,"待更新部门不存在");
        SysDept after = new SysDept();
        BeanUtils.copyProperties(deptVo,after);
        after.setOperator(RequestHolder.getCurrentUser().getUsername());
        after.setOperateIp(IpUtil.getUserIP(RequestHolder.getCurrentRequest()));
        after.setLevel(LevelUtil.calculateLevel(getLevel(deptVo.getParentId()),deptVo.getParentId()));
        updateWithChild(before,after);
    }

    @Override
    public void delete(Integer id) {
        SysDept dept = deptMapper.selectByPrimaryKey(id);
        if(dept==null){
            throw new ParamException("不存在此部门");
        }
        deleteWithChild(dept);
    }

    @Transactional
    public void deleteWithChild(SysDept dept) {
        List<SysDept> deptList = deptMapper.getChildDeptListByLevel(dept.getLevel()+"."+dept.getId()+"%");
        if(CollectionUtils.isNotEmpty(deptList)){
            for(SysDept sysDept:deptList){
                deptMapper.deleteByPrimaryKey(sysDept.getId());
                userMapper.deleteByDeptId(sysDept.getId());
            }
        }
        deptMapper.deleteByPrimaryKey(dept.getId());
        userMapper.deleteByDeptId(dept.getId());
    }

    @Transactional
    public void updateWithChild(SysDept before,SysDept after){

        String nextLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if(!nextLevelPrefix.equals(oldLevelPrefix)){
            List<SysDept> deptList = deptMapper.getChildDeptListByLevel(before.getLevel()+"."+before.getId());
            if(CollectionUtils.isNotEmpty(deptList)){
                for(SysDept dept:deptList){
                    String level = dept.getLevel();
                    if(level.indexOf(oldLevelPrefix)==0){
                        level = nextLevelPrefix+level.substring(oldLevelPrefix.length());
                        dept.setLevel(level);
                    }
                }
                deptMapper.batchUpdateLevel(deptList);
            }
        }
        deptMapper.updateByPrimaryKey(after);
        logService.saveDeptLog(before,after);
    }

    private boolean checkExist(Integer parentId,String deptName,Integer deptId){
        int count = deptMapper.countByNameAndParentId(parentId,deptName,deptId);
        if(count>0){
            return true;
        }
        return false;
    }
    private String getLevel(Integer deptId){
        SysDept dept = deptMapper.selectByPrimaryKey(deptId);
        if(dept==null){
            return null;
        }
        return dept.getLevel();
    }
}
